import 'dart:async';

import 'package:flutter/material.dart';

/// 页面 body
class BlocBody extends StatelessWidget {
  const BlocBody({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    CounterBloc _bloc = CounterProvider.of(context).bloc;

    return ListView(
      children: <Widget>[
        ListTile(
          title: Text('BloC(Business Logic Component)'),
          subtitle: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Text('''
- 反应式编程(响应式);
  异步数据流进行编程;
- 事件流 & 数据流;
- Widget 监听数据流, 发起事件流;
  监听: StreamBuilder(
                    initialData: 0,
                    stream: _bloc._dataStreamController.stream,
                    builder: (BuildContext context, AsyncSnapshot<int> snapshot) {},
                  )
  发起: _bloc._actionStreamController.sink.add(1);
- Bloc 监事件流, 发起数据流;
  监听: _actionStreamController.stream.listen((data) {});
  发起: _dataStreamController.add(_count);
- 不需要 State 概念, 不再使用 setState(() {}), 所有内容通过 Stream 接收;
                  '''),
              ),
              Wrap(
                spacing: 8.0,
                children: <Widget>[
                  Chip(
                    label: Text('broadcast(多监听):'),
                    backgroundColor: Colors.transparent,
                  ),
                  StreamBuilder(
                    initialData: 0,
                    stream: _bloc._dataStreamController.stream,
                    builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                      return ActionChip(
                        label: Text('${snapshot.data}'),
                        onPressed: () {
                          _bloc._actionStreamController.sink.add(1);
                        },
                      );
                    },
                  ),
                  StreamBuilder(
                    initialData: 0,
                    stream: _bloc._dataStreamController.stream, // Widget 监听数据流
                    builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
                      return ActionChip(
                        label: Text('${snapshot.data}'),
                        onPressed: () {
                          // Widget 发起事件流
                          _bloc._actionStreamController.sink.add(1);
                        },
                      );
                    },
                  ),
                ],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: <Widget>[
                  CountAddButton(),
                ],
              ),
            ],
          ),
        ),
        Divider(height: 1.0),
      ],
    );
  }
}

/// 子 Widget
class CountAddButton extends StatelessWidget {
  const CountAddButton({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    CounterBloc _bloc = CounterProvider.of(context).bloc;
    return RaisedButton(
      onPressed: () {
        // Widget 发起事件流
        _bloc._actionStreamController.sink.add(1);
      },
      child: Text('Add'),
    );
  }
}

/// 用于穿透各 Widgets 的 Provider(提供者)
class CounterProvider extends InheritedWidget {
  CounterProvider({Key key, this.child, this.bloc}) : super(key: key, child: child);

  final Widget child;
  final CounterBloc bloc;

  static CounterProvider of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType(aspect: CounterProvider);
  }

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return true;
  }
}

/// 处理业务逻辑
class CounterBloc {
  /// 事件流控制器
  final _actionStreamController = StreamController<int>.broadcast();

  /// 数据
  int _count = 0;

  /// 数据流控制器
  final _dataStreamController = StreamController<int>.broadcast();

  /// 构造函数里初始化监听器
  CounterBloc() {
    // Bloc 监听 Widget 的事件流
    _actionStreamController.stream.listen((data) {
      // 收到监听
      print(data);

      _count += data;

      // Bloc 发起数据流
      _dataStreamController.sink.add(_count);
    });
  }

  dispose() {
    _actionStreamController.close();
    _dataStreamController.close();
  }
}
